var Dom = (function () {
	var getStyle = function (node, name) {
		if (node.currentStyle) { // ie, opera
			return node.currentStyle[name];
		} else if (window.getComputedStyle) { // ff, chrome, safari
			return window.getComputedStyle(node, null)[name];
		}
	};

	var getPos = function (node, root) {
		var x = 0,
			y = 0,
			parent,
			doc = document,
			nodeRect,
			rootRect;

		node = node;
		root = root || doc.body;

		// Returns the x, y cordinate for an element on IE 6 and IE 7
		function getIEPos(node) {
			var bodyElm, rect, x = 0, y = 0;

			if (node) {
				rect = node.getBoundingClientRect();
				bodyElm = doc.compatMode === "CSS1Compat" ? doc.documentElement : doc.body;
				x = rect.left + bodyElm.scrollLeft;
				y = rect.top + bodyElm.scrollTop;
			}

			return {
				x: x,
				y: y
			};
		}

		// Use getBoundingClientRect on IE 6 and IE 7 but not on IE 8 in standards mode
		if (node && node.getBoundingClientRect && (!!window.ActiveXObject || "ActiveXObject" in window) && (!doc.documentMode || doc.documentMode < 8)) {
			nodeRect = getIEPos(node);
			rootRect = getIEPos(root);

			return {
				x: nodeRect.x - rootRect.x,
				y: nodeRect.y - rootRect.y
			};
		}

		parent = node;
		while (parent && parent != root && parent.nodeType) {
			x += parent.offsetLeft || 0;
			y += parent.offsetTop || 0;
			parent = parent.offsetParent;
		}

		parent = node.parentNode;
		while (parent && parent != root && parent.nodeType) {
			x -= parent.scrollLeft || 0;
			y -= parent.scrollTop || 0;
			parent = parent.parentNode;
		}

		return {
			x: x,
			y: y
		};
	};

	var getSize = function (node) {
		return {
			w: node.offsetWidth || node.clientWidth,
			h: node.offsetHeight || node.clientHeight
		};
	};

	var overOn = function (shimContainer, target) {
		var me = this,
			container = target.parentNode,
			pos, size;

		// make container relative, if it's not
		if ('static' === Dom.getStyle(container, 'position')) {
			container.style.position = 'relative';
		}

		pos = me.getPos(target, container);
		size = me.getSize(target);

		$.extend(shimContainer.style, {
			position: 'absolute',
			top: pos.y + 'px',
			left: pos.x + 'px',
			width: size.w + 'px',
			height: size.h + 'px',
			opacity: 0.8,
			filter: 'alpha(opacity=80)',
			background: '#000'
		});

		container.appendChild(shimContainer);
	};

	var hasClass = function (obj, name) {
		if (!obj.className) {
			return false;
		}

		var regExp = new RegExp("(^|\\s+)" + name + "(\\s+|$)");
		return regExp.test(obj.className);
	};

	var addClass = function (obj, name) {
		if (!hasClass(obj, name)) {
			obj.className = !obj.className ? name : obj.className.replace(/\s+$/, '') + ' ' + name;
		}
	};

	var removeClass = function (obj, name) {
		if (obj.className) {
			var regExp = new RegExp("(^|\\s+)" + name + "(\\s+|$)");
			obj.className = obj.className.replace(regExp, function ($0, $1, $2) {
				return $1 === ' ' && $2 === ' ' ? ' ' : '';
			});
		}
	};

	var addEvent = document.addEventListener ?
		function (elem, type, fn) {
			elem.addEventListener(type, fn, false);
		} : function (elem, type, fn) {
		elem.attachEvent('on' + type, fn);
	};

	function parseJSON(str) {
		if (typeof(str) === 'object') {
			return str;
		} else {
			if (window.JSON) {
				return JSON.parse(str);
			} else {
				return eval('(' + str + ')');
			}
		}
	}

	function get(selector) {
		var doc = document;
		return doc.querySelector && doc.querySelector(selector) || doc.getElementById(selector);
	}

	return {
		get: get,
		getStyle: getStyle,
		getPos: getPos,
		getSize: getSize,
		overOn: overOn,
		hasClass: hasClass,
		addClass: addClass,
		removeClass: removeClass,
		on: addEvent
	};
})();
